package com.ruochen.common.base;

import android.text.TextUtils;
import android.util.Log;

import androidx.annotation.NonNull;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONException;
import com.alibaba.fastjson.JSONObject;
import com.blankj.utilcode.util.AppUtils;
import com.blankj.utilcode.util.LogUtils;
import com.blankj.utilcode.util.NetworkUtils;
import com.blankj.utilcode.util.StringUtils;
import com.google.gson.GsonBuilder;
import com.ruochen.common.BuildConfig;
import com.ruochen.common.utils.HYLEncryptionUtil;
import com.ruochen.common.utils.HttpsUtils;
import com.ruochen.common.utils.SerializableSpTools;
import com.ruochen.common.utils.SystemUtil;

import java.io.IOException;
import java.nio.charset.Charset;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.TimeUnit;

import okhttp3.CacheControl;
import okhttp3.FormBody;
import okhttp3.Headers;
import okhttp3.HttpUrl;
import okhttp3.Interceptor;
import okhttp3.MediaType;
import okhttp3.MultipartBody;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import okhttp3.ResponseBody;
import okhttp3.logging.HttpLoggingInterceptor;
import retrofit2.Retrofit;
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;
import retrofit2.converter.gson.GsonConverterFactory;

/**
 * @描述: 访问网络构造
 * @作者: 宋俊 SongJun
 * @时间: 2016/11/11 14:33
 * @版权: 华创云科技有限公司
 * @官网: http://www.gzytkj.net/
 */
class AppClient {
    private final static int DEFAULT_TIMEOUT = 40;
    private static Retrofit mAppRetrofit;
    private static OkHttpClient okHttpClient;

    static Retrofit getAppRetrofit() {
        if (mAppRetrofit == null) {
            mAppRetrofit = new Retrofit.Builder()
                    .baseUrl(BuildConfig.SERVER_HOST)
                    .addConverterFactory(GsonConverterFactory.create(new GsonBuilder()
                            .setDateFormat("yyyy-MM-dd HH:mm:ss")
                            .create()))
                    .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                    .client(getOkHttpClient())
                    .build();
        }
        return mAppRetrofit;
    }

    private static OkHttpClient getOkHttpClient() {
        if (okHttpClient == null) {
            OkHttpClient.Builder builder = new OkHttpClient.Builder();
            if (BuildConfig.DEBUG) {
                // Log信息拦截器
                HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor();
                loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
                //设置 Debug MyLog 模式
                builder.addInterceptor(loggingInterceptor);
            }
            /*File httpCacheDirectory = new File(AppApplication.getInstances()
                    .getExternalCacheDir(), "responses");
            int cacheSize = 10 * 1024 * 1024; // 10 MiB
            Cache cache = new Cache(httpCacheDirectory, cacheSize);
            builder.cache(cache);*/
            HttpsUtils.SSLParams sslParams = HttpsUtils.getSslSocketFactory();
            builder.addInterceptor(new TokenHeaderInterceptor())
                    .addInterceptor(new ParameterInterceptor())
                    .connectTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS)
                    .writeTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS)
                    .readTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS)
                    .sslSocketFactory(sslParams.sSLSocketFactory, sslParams.trustManager);
            //okHttpClient = RetrofitUrlManager.getInstance().with(builder).build();
            okHttpClient = builder.build();
        }
        return okHttpClient;
    }

    private static class TokenHeaderInterceptor implements Interceptor {

        @Override
        public Response intercept(Chain chain) throws IOException {
            String token = SerializableSpTools.getToken();
            Request.Builder updateRequestBuild = chain.request().newBuilder();
            if (!StringUtils.isTrimEmpty(token)) {
                LogUtils.e("token", token);
                updateRequestBuild.header("token", token);
            }
            updateRequestBuild.header("Form", "android");
            updateRequestBuild.header("AppPackageName", AppUtils.getAppPackageName());
            updateRequestBuild.header("AppVersionName", AppUtils.getAppVersionName());
            updateRequestBuild.header("AppVersionCode", AppUtils.getAppVersionCode() + "");
            updateRequestBuild.header("AndroidVersion", SystemUtil.getSystemVersion());
            updateRequestBuild.header("DeviceBrand", SystemUtil.getDeviceBrand());
            updateRequestBuild.header("SystemModel", SystemUtil.getSystemModel());
            return chain.proceed(updateRequestBuild.build());
        }
    }

    //cache
    private static class RewriteCacheControlInterceptor implements Interceptor {
        @Override
        public Response intercept(Chain chain) throws IOException {
            CacheControl.Builder cacheBuilder = new CacheControl.Builder();
            cacheBuilder.maxAge(0, TimeUnit.SECONDS);
            cacheBuilder.maxStale(365, TimeUnit.DAYS);
            CacheControl cacheControl = cacheBuilder.build();

            Request request = chain.request();
            if (!NetworkUtils.isConnected()) {
                request = request.newBuilder()
                        .cacheControl(cacheControl)
                        .build();
            }
            Response originalResponse = chain.proceed(request);
            if (!NetworkUtils.isConnected()) {
                int maxAge = 0; // read from cache
                return originalResponse.newBuilder()
                        .removeHeader("Pragma")
                        .header("Cache-Control", "public ,max-age=" + maxAge)
                        .build();
            } else {
                int maxStale = 60 * 60 * 24 * 28; // tolerate 4-weeks stale
                return originalResponse.newBuilder()
                        .removeHeader("Pragma")
                        .header("Cache-Control", "public, only-if-xcached, max-stale=" + maxStale)
                        .build();
            }
        }
    }

    ;

    public static class ParameterInterceptor implements Interceptor {

        @Override
        public Response intercept(Chain chain) throws IOException {
            Request oldRequest = chain.request();
//        if ("get".equals(oldRequest.method())) return chain.proceed(newBuilder.build());
            RequestBody requestBody = makeRequestBody(oldRequest);
            HttpUrl httpUrl = oldRequest.url().newBuilder().build();

            Headers.Builder builder = new Headers.Builder();

            if (TextUtils.isEmpty(oldRequest.header("Content-Type"))) {
                builder.add("Content-Type", "application/json");
                builder.add("Accept", "application/json");
                builder.add("Connection", "close");
            } else {
                builder.add("Content-Type", oldRequest.header("Content-Type"));
                builder.add("Connection", "Keep-Alive");
            }
            builder.add("token", SerializableSpTools.getToken());
            Request.Builder newBuilder = oldRequest.newBuilder()
                    .url(httpUrl)
                    .headers(oldRequest.headers())
                    .headers(builder.build());

            if (TextUtils.equals(oldRequest.method().toLowerCase(), "post")) {
                newBuilder.post(requestBody);
            } else if (TextUtils.equals(oldRequest.method().toLowerCase(), "get")) {
                newBuilder.get();
            } else if (TextUtils.equals(oldRequest.method().toLowerCase(), "put")) {
                newBuilder.put(requestBody);
            } else if (TextUtils.equals(oldRequest.method().toLowerCase(), "delete")) {
                newBuilder.delete(requestBody);
            }

            Response response = chain.proceed(newBuilder.build());

            ResponseBody resultBody = response.body();
            String result = resultBody.string();

            JSONObject jsonObject = null;
            try {
                if (TextUtils.isEmpty(result)) {
                    jsonObject = new JSONObject();
                } else {
                    jsonObject = JSONObject.parseObject(result);
                }

                //打印返回数据
                if (BuildConfig.DEBUG && !TextUtils.isEmpty(result)) {
                    try {
                        Log.d("Request", result);
                    } catch (Exception e1) {
                        e1.printStackTrace();
                    }
                }
                /*** void.string()后即关闭，后续无法获取内容 */
                return response.newBuilder()
                        .body(ResponseBody.create(resultBody.contentType(), jsonObject.toString()))
                        .build();

            } catch (JSONException e) {
                e.printStackTrace();
            }

            /*** 因为调用ResponseBody.string()后即关闭，后续无法获取内容 */
            return response.newBuilder()
                    .body(ResponseBody.create(resultBody.contentType(), result))
                    .build();
        }

        @NonNull
        private RequestBody makeRequestBody(Request oldRequest) {
            HashMap<String, Object> params = new HashMap<>();

            if (oldRequest.body() instanceof FormBody) {
                /*** 当参数以 @Field @FieldMap 提交时 */
                FormBody body = (FormBody) oldRequest.body();
                if (body != null)
                    for (int i = body.size() - 1; i >= 0; i--) {
                        String name = body.name(i);
                        String value = body.value(i);
                        if (value.contains("[") && value.contains("]")) {
                            JSONArray jsonArray = null;
                            try {
                                jsonArray = JSONObject.parseArray(value);
                            } catch (Exception e) {
                            }
                            params.put(name, null == jsonArray ? value : jsonArray);
                        } else {
                            params.put(name, value);
                        }
                    }
            } else if (oldRequest.body() instanceof MultipartBody) {
                /*** 当参数以 @MultipartBody 提交时 */
                MultipartBody.Builder builder = new MultipartBody.Builder();
                builder.setType(MultipartBody.FORM);//以表单提交 必须设置
                List<MultipartBody.Part> parts = ((MultipartBody) oldRequest.body()).parts();

                for (MultipartBody.Part part : parts) {
                    if (!(part.body() instanceof FormBody)) {
                        builder.addPart(part);//添加文件
                        continue;
                    }
                    FormBody formBody = (FormBody) part.body();
                    for (int index = 0; index < formBody.size(); index++) {
                        String value = formBody.encodedValue(index);
                        JSONObject jsonObject = null;
                        try {
                            jsonObject = JSONObject.parseObject(value);
                        } catch (Exception e) {
                        }
                        params.put(formBody.encodedName(index), null == jsonObject ? value : jsonObject);
                    }
                }

                Log.e("ParameterInterceptor", "请求参数：MultipartBody" + params.toString());
                return builder.build();
            } else {
                RequestBody requestBody = oldRequest.body();
                if (requestBody != null) {
                    okio.Buffer buffer = new okio.Buffer();
                    try {
                        requestBody.writeTo(buffer);
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                    Charset charset = Charset.forName("UTF-8");
                    MediaType contentType = requestBody.contentType();
                    if (contentType != null) {
                        charset = contentType.charset(charset);
                    }
                    String string = buffer.readString(charset);
                    //模拟加密的方法，这里调用大家自己的加密方法就可以了
                    String encryptStr = HYLEncryptionUtil.encryption(string);
                    return MultipartBody.create(contentType, encryptStr);

                }
            }

            Log.w("ParameterInterceptor", "请求参数：" + params.toString());
            //开始加密
            String paramsJson = JSON.toJSON(params).toString();
            String encryptionParams = HYLEncryptionUtil.encryption(paramsJson);
            Log.w("ParameterInterceptor", "请求参数：" + encryptionParams.toString());
            return RequestBody.create(MediaType.parse("application/json;charset=UTF-8"), paramsJson);
        }
    }


}
